﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using Turismo.Negocio.EntidadesGeometricas;
using EstructurasDeDatos;
using EstructurasDeDatos.EstructuraGrafo;
using Persistencia.NHibernate;
using NHibernate;
using GeoAPI.Geometries;


namespace Turismo.Negocio.Analisis
{
    public class CGuia
    {
        public CGuia()
        {
        }

        public Grafo<Cabecera, Medio> buscarRutas(Cabecera Origen, Cabecera Destino, int Cambios, int PesoDinero, Boolean TransportePrivado)
        {
            TimeSpan Duracion = new TimeSpan(0, 0, 0);
            ListaNodos<Cabecera> Rutas = this.construirGrafo(Origen, Destino, Cambios, Duracion, TransportePrivado);
            Grafo<Cabecera, Medio> Resultado = new Grafo<Cabecera, Medio>(Rutas);
            if (Rutas != null)
            {
                NodoGrafo<Cabecera, Medio> puntodestino = new NodoGrafo<Cabecera, Medio>(Destino, (Medio)null);
                Rutas.Add(puntodestino);
                this.calcularPesos(Rutas, ((double)PesoDinero / (double)100));
            }
            return Resultado;
        }

        private ListaNodos<Cabecera> buscarVuelos(Cabecera Origen, Cabecera Destino, int Cambios, TimeSpan Duracion)
        {
            if (Cambios == 0)
                return null;
            NHibernatePersistencia BD = (NHibernatePersistencia)NHibernatePersistencia.Instancia;
            //Busca las rutas directas
            ISQLQuery ConsultaVuelosDirectos = BD.Session.CreateSQLQuery("select distinct v.id " +
                                                     "from vuelos v, enlaza e " +
                                                     "where v.id_enlace = e.id and " +
                                                     "v.hora = (select MIN(r.hora) from vuelos r where r.id_enlace=v.id_enlace and r.id_operador=v.id_operador and r.hora > convert(time,?)) and " +
                                                     "e.id_cab_ini=? and " +
                                                     "e.id_cab_fin=? and " +
                                                     "v.dia = ?");
            //DateTime Ahora = DateTime.Now;
            DateTime Ahora = new DateTime(2011, 5, 19, 15, 0, 0);
            Ahora.Add(Duracion);
            ConsultaVuelosDirectos.SetTime(0,Ahora);
            ConsultaVuelosDirectos.SetInt32(1, Origen.Id);
            ConsultaVuelosDirectos.SetInt32(2, Destino.Id);
            String Dia = "";
            switch (Ahora.DayOfWeek)
            {
                case DayOfWeek.Monday:
                    Dia = "lunes";
                    break;
                case DayOfWeek.Tuesday:
                    Dia = "martes";
                    break;
                case DayOfWeek.Wednesday:
                    Dia = "miercoles";
                    break;
                case DayOfWeek.Thursday:
                    Dia = "jueves";
                    break;
                case DayOfWeek.Friday:
                    Dia = "viernes";
                    break;
                case DayOfWeek.Saturday:
                    Dia = "sabado";
                    break;
                case DayOfWeek.Sunday:
                    Dia = "domingo";
                    break;
            }
            ConsultaVuelosDirectos.SetString(3, Dia);
            IList<object> Resultados = ConsultaVuelosDirectos.List<object>();
            NodoGrafo<Cabecera, Medio> punto = new NodoGrafo<Cabecera, Medio>(Origen, (Medio)null);
            ListaNodos<Cabecera> ListaVecinos = new ListaNodos<Cabecera>();
            punto.Vecinos = ListaVecinos;
            ListaNodos<Cabecera> Lista = new ListaNodos<Cabecera>();
            Lista.Add(punto);
            foreach (int IdVuelo in Resultados)
            {
                IQuery ConsultaVuelo = BD.Session.CreateQuery("from Vuelo where id=?");
                ConsultaVuelo.SetInt32(0, IdVuelo);
                IList<Vuelo> ResultadoVuelo = ConsultaVuelo.List<Vuelo>();
                NodoGrafo<Cabecera, Medio> PuntoDestino = new NodoGrafo<Cabecera, Medio>(Destino, ResultadoVuelo.First());
                ListaVecinos.Add(PuntoDestino);
            }
            //Busca vuelos que pasen por el origen
            ISQLQuery Consulta = BD.Session.CreateSQLQuery("select distinct v.id, e.id_cab_fin " +
                                                     "from vuelos v, enlaza e " +
                                                     "where v.id_enlace = e.id and " +
                                                     "v.hora = (select MIN(r.hora) from vuelos r where r.id_enlace=v.id_enlace and r.id_operador=v.id_operador and r.hora > convert(time,?)) and " +
                                                     "e.id_cab_ini=? and " +
                                                     "v.dia = ?");
            Consulta.SetTime(0, Ahora);
            Consulta.SetInt32(1, Origen.Id);
            Consulta.SetString(2, Dia);
            Resultados = Consulta.List<object>();
            foreach (Object[] o in Resultados)
            {
                IQuery ConsultaVuelo = BD.Session.CreateQuery("from Vuelo where id=?");
                ConsultaVuelo.SetInt32(0, (int)o[0]);
                IList<Vuelo> ResultadoVuelos = ConsultaVuelo.List<Vuelo>();
                IQuery ConsultaCabecera = BD.Session.CreateQuery("from Cabecera where id=?");
                ConsultaCabecera.SetInt32(0, (int)o[1]);
                IList<Cabecera> ResultadoCabecera = ConsultaCabecera.List<Cabecera>();
                NodoGrafo<Cabecera, Medio> destino = new NodoGrafo<Cabecera, Medio>(ResultadoCabecera.First(), ResultadoVuelos.First());
                if (Cambios - 1 >= 0 && ResultadoCabecera.First().Id != Destino.Id)
                {
                    TimeSpan DuracionVuelo = this.calcularDuracionVuelo(ResultadoVuelos.First<Vuelo>());
                    TimeSpan DuracionViaje = new TimeSpan(Duracion.Hours, Duracion.Minutes, Duracion.Seconds);
                    DuracionViaje.Add(DuracionVuelo);
                    ListaNodos<Cabecera> siguientes = this.buscarVuelos(ResultadoCabecera.First(), Destino, (Cambios - 1), DuracionViaje);
                    if (siguientes != null)//Si no hay siguientes no llega al destino entonces no se incluye
                    {
                        ListaVecinos.Add(destino);
                        foreach (NodoGrafo<Cabecera, Medio> nodo in siguientes)
                        {
                            NodoGrafo<Cabecera, Medio> nodoexistente = (NodoGrafo<Cabecera, Medio>)Lista.FindByValue(nodo.Valor);
                            if (nodoexistente == null)
                                Lista.Add(nodo);
                            else
                            {
                                foreach (NodoGrafo<Cabecera, Medio> visitados in nodo.Vecinos)
                                    nodoexistente.Vecinos.Add(visitados);
                            }
                        }
                    }
                }
                if (ResultadoCabecera.First().Id == Destino.Id)
                    ListaVecinos.Add(destino);
            }
            if (ListaVecinos.Count == 0)
                return null;
            return Lista;
        }

        private ListaNodos<Cabecera> construirGrafo(Cabecera Origen, Cabecera Destino, int Cambios, TimeSpan Duracion, Boolean TransportePrivado)
        {
            if (Cambios == 0)
                return null;
            NHibernatePersistencia BD = (NHibernatePersistencia)NHibernatePersistencia.Instancia;
            //Busca las rutas directas
            ISQLQuery ConsultaRutasDirectas = BD.Session.CreateSQLQuery("select distinct s.id " +
                                                     "from servicio s, ruta r, recorridos re, caminos c, tramos t " +
                                                     "where s.id_ruta = r.id and " +
                                                     "re.id_ruta = r.id and " +
                                                     "re.id_camino = c.id_camino and " +
                                                     "c.id_tramo = t.id and " +
                                                     "t.id_cab_ini=? and " +
                                                     //"s.hora = (select MIN(r.hora) from servicio r where r.id_ruta=s.id_ruta and r.id_operador=s.id_operador and r.hora > convert(time,?)) and " + 
                                                     "s.hora > convert(time,?) and " + 
                                                     "s.id in ( select distinct s.id " +
                                                     "from servicio s, ruta r, recorridos re, caminos c, tramos t " +
                                                     "where s.id_ruta = r.id and " +
                                                     "re.id_ruta = r.id and " +
                                                     "re.id_camino = c.id_camino and " +
                                                     "c.id_tramo = t.id and " +
                                                     "t.id_cab_fin=? ) and " +
                                                     "s.dia = ?");
            DateTime Ahora = DateTime.Now;
            Ahora.Add(Duracion);
            ConsultaRutasDirectas.SetTime(1, Ahora);
            ConsultaRutasDirectas.SetInt32(0, Origen.Id);
            ConsultaRutasDirectas.SetInt32(2, Destino.Id);
            String Dia = "";
            switch (Ahora.DayOfWeek)
            {
                case DayOfWeek.Monday:
                    Dia = "lunes";
                    break;
                case DayOfWeek.Tuesday:
                    Dia = "martes";
                    break;
                case DayOfWeek.Wednesday:
                    Dia = "miercoles";
                    break;
                case DayOfWeek.Thursday:
                    Dia = "jueves";
                    break;
                case DayOfWeek.Friday:
                    Dia = "viernes";
                    break;
                case DayOfWeek.Saturday:
                    Dia = "sabado";
                    break;
                case DayOfWeek.Sunday:
                    Dia = "domingo";
                    break;
            }
            ConsultaRutasDirectas.SetString(3, Dia);
            IList<object> Resultados = ConsultaRutasDirectas.List<object>();
            NodoGrafo<Cabecera, Medio> punto = new NodoGrafo<Cabecera, Medio>(Origen, (Medio)null);
            ListaNodos<Cabecera> ListaVecinos = new ListaNodos<Cabecera>();
            punto.Vecinos = ListaVecinos;
            ListaNodos<Cabecera> Lista = new ListaNodos<Cabecera>();
            Lista.Add(punto);
            foreach (int IdServicio in Resultados)
            {
                IQuery ConsultaServicio = BD.Session.CreateQuery("from Servicio where id=?");
                ConsultaServicio.SetInt32(0, IdServicio);
                IList<Servicio> ResultadoServicios = ConsultaServicio.List<Servicio>();
                NodoGrafo<Cabecera, Medio> PuntoDestino = new NodoGrafo<Cabecera, Medio>(Destino, (Servicio)ResultadoServicios.First());
                ListaVecinos.Add(PuntoDestino);
            }
            //Busca rutas que pasen por el origen
            Resultados = this.consultarServiciosDisponibles(Origen, Ahora, Dia);
            foreach (int[] o in Resultados)
            {
                IQuery ConsultaServicio = BD.Session.CreateQuery("from Servicio where id=?");
                ConsultaServicio.SetInt32(0, o[0]);
                IList<Servicio> ResultadoServicios = ConsultaServicio.List<Servicio>();
                IQuery ConsultaCabecera = BD.Session.CreateQuery("from Cabecera where id=?");
                ConsultaCabecera.SetInt32(0, o[1]);
                IList<Cabecera> ResultadoCabecera = ConsultaCabecera.List<Cabecera>();
                NodoGrafo<Cabecera,Medio> destino = new NodoGrafo<Cabecera,Medio>(ResultadoCabecera.First(), ResultadoServicios.First());
                if (Cambios - 1 >= 0 && ResultadoCabecera.First().Id != Destino.Id)
                {
                    TimeSpan DuracionServicio = this.calcularDuracionServicio(ResultadoServicios.First<Servicio>(), Origen, ResultadoCabecera.First(), Ahora);
                    TimeSpan DuracionViaje = new TimeSpan(Duracion.Hours, Duracion.Minutes, Duracion.Seconds);
                    DuracionViaje.Add(DuracionServicio);
                    ListaNodos<Cabecera> siguientes = this.construirGrafo(ResultadoCabecera.First(), Destino, (Cambios - 1), DuracionViaje, false);
                    if (siguientes != null)//Si no hay siguientes no llega al destino entonces no se incluye
                    {
                        ListaVecinos.Add(destino);
                        //Adiciona los vuelos disponibles para el primer tramo
                        ListaNodos<Cabecera> vuelos = this.buscarVuelos(Origen, ResultadoCabecera.First(), 0, DuracionViaje);
                        if (vuelos != null)
                        {
                            foreach (NodoGrafo<Cabecera, Medio> NG in vuelos)//Siempre se hace una sola vez
                            {
                                foreach (NodoGrafo<Cabecera, Medio> visitados in NG.Vecinos)
                                    ListaVecinos.Add(visitados);
                            }
                        }
                        foreach (NodoGrafo<Cabecera,Medio> nodo in siguientes)
                        {
                            NodoGrafo<Cabecera,Medio> nodoexistente = (NodoGrafo<Cabecera,Medio>)Lista.FindByValue(nodo.Valor);
                            if (nodoexistente == null)
                                Lista.Add(nodo);
                            else
                            {
                                foreach (NodoGrafo<Cabecera, Medio> visitados in nodo.Vecinos)
                                {
                                    Boolean esta=false;
                                    foreach (NodoGrafo<Cabecera, Medio> v in nodoexistente.Vecinos)
                                    {
                                        if (v.Medio.GetType() == visitados.Medio.GetType() && v.Medio.Id == visitados.Medio.Id)
                                            esta = true;
                                    }
                                    if(!esta)
                                        nodoexistente.Vecinos.Add(visitados);
                                }
                            }
                        }
                    }
                }
            }
            //Busca vuelos entre el origen y el destino
            ListaNodos<Cabecera> ListaVuelos = this.buscarVuelos(Origen, Destino, Cambios, Duracion);
            if (ListaVuelos != null)
            {
                foreach (NodoGrafo<Cabecera, Medio> nodo in ListaVuelos)
                {
                    NodoGrafo<Cabecera, Medio> nodoexistente = (NodoGrafo<Cabecera, Medio>)Lista.FindByValue(nodo.Valor);
                    if (nodoexistente == null)
                        Lista.Add(nodo);
                    else
                    {
                        foreach (NodoGrafo<Cabecera, Medio> visitados in nodo.Vecinos)
                        {
                            Boolean esta = false;
                            foreach (NodoGrafo<Cabecera, Medio> intervalo in nodoexistente.Vecinos)
                            {
                                if (intervalo.Medio is Vuelo && intervalo.Valor.Id == visitados.Valor.Id && ((Vuelo)intervalo.Medio).Id == ((Vuelo)visitados.Medio).Id)
                                    esta = true;
                            }
                            if (!esta)
                                nodoexistente.Vecinos.Add(visitados);
                        }
                    }
                }
            }
            if (TransportePrivado)
            {
                List<List<Via>> Caminos = buscarCaminos(Origen, Destino);
                if (Caminos != null)
                {
                    foreach (List<Via> l in Caminos)
                    {
                        Viaje viaje = new Viaje();
                        viaje.Vias = l;
                        NodoGrafo<Cabecera, Medio> PuntoDestino = new NodoGrafo<Cabecera, Medio>(Destino, viaje);
                        ListaVecinos.Add(PuntoDestino);
                    }
                }
            }
            if (ListaVecinos.Count == 0)
                return null;
            return Lista;
        }

        private List<List<Via>> buscarCaminos(Cabecera Origen, Cabecera Destino)
        {
            List<List<Via>> Caminos = new List<List<Via>>();
            NHibernatePersistencia BD = (NHibernatePersistencia)NHibernatePersistencia.Instancia;
            ISQLQuery ConsultaVias = BD.Session.CreateSQLQuery("select v.id " +
                                                               "from vias v, cabeceras c " +
                                                               "where v.geom.STIntersects(c.geom.STBuffer(2000))=1 "+
                                                               "and c.id = ?");
            ConsultaVias.SetInt32(0,Origen.Id);
            IList<int> ViasIniciales = ConsultaVias.List<int>();
            foreach(int i in ViasIniciales)
            {
                Via v = BD.Obtener<Via>(i);
                List<List<Via>> Vias = buscarVias(v, null,Destino);
                if (Vias != null)
                {
                    foreach (List<Via> l in Vias)
                        Caminos.Add(l);
                }
            }
            if (Caminos.Count == 0)
                return null;
            else
                return Caminos;
        }

        private List<List<Via>> buscarVias(Via Camino, Via Anterior, Cabecera Destino)
        {
            List<List<Via>> Caminos = new List<List<Via>>();
            NHibernatePersistencia BD = (NHibernatePersistencia)NHibernatePersistencia.Instancia;
            ISQLQuery ConsultaVias = BD.Session.CreateSQLQuery("select v.id " +
                                                               "from vias v, vias v1 " +
                                                               "where (v.geom.STIntersects(v1.geom)=1 "+
                                                               "or v.geom.STTouches(v1.geom)=1) " +
                                                               "and v.id != ? "+
                                                               "and v1.id = ? "+
                                                               "and v.id != v1.id");
            if(Anterior != null)
                ConsultaVias.SetInt32(0, Anterior.Id);
            else
                ConsultaVias.SetInt32(0, -1);
            ConsultaVias.SetInt32(1, Camino.Id);
            Double RadioCubrimientoDeCamino = 0;
            RadioCubrimientoDeCamino = Camino.Geometria.Distance(Destino.Geometria);
            IList<int> ViasIniciales = ConsultaVias.List<int>();
            foreach (int i in ViasIniciales)
            {
                Via v = BD.Obtener<Via>(i);
                if (v.Geometria.Intersects(Destino.Geometria.Buffer(2000)))
                {
                    List<Via> Vias = new List<Via>();
                    Vias.Add(Camino);
                    Vias.Add(v);
                    Caminos.Add(Vias);
                }
                else
                {
                    if (v.Geometria.Distance(Destino.Geometria) < RadioCubrimientoDeCamino)
                    {
                        List<List<Via>> CaminosSiguientes = buscarVias(v, Camino, Destino);
                        if (CaminosSiguientes != null)
                        {
                            foreach (List<Via> l in CaminosSiguientes)
                            {
                                List<Via> Vias = new List<Via>();
                                Vias.Add(Camino);
                                foreach (Via ViaSiguiente in l)
                                    Vias.Add(ViaSiguiente);
                                Caminos.Add(Vias);
                            }
                        }
                    }
                }
            }
            if (Caminos.Count == 0)
                return null;
            else
                return Caminos;
        }

        private TimeSpan calcularDuracionVuelo(Vuelo vuelo)
        {
            double distancia = vuelo.Enlace.CabeceraInicial.Geometria.Distance(vuelo.Enlace.CabeceraFinal.Geometria)/1000;
            double horas = distancia / 700;
            int CantHoras = (int)horas;
            int CantMinutos = (int)((horas - CantHoras)*60);
            int CantSegundos = (int)(((horas - CantHoras)*60 - CantMinutos)*60);
            TimeSpan Resultado = new TimeSpan(CantHoras, CantMinutos, CantSegundos);
            return Resultado;
        }

        private TimeSpan calcularDuracionServicio(Servicio servicio, Cabecera Origen, Cabecera Destino, DateTime Hora)
        {
            NHibernatePersistencia BD = (NHibernatePersistencia)NHibernatePersistencia.Instancia;
            IQuery ConsultaRecorridos = BD.Session.CreateQuery("from Recorrido where Ruta.Id=? order by Orden");
            ConsultaRecorridos.SetInt32(0, servicio.Ruta.Id);
            IList<Recorrido> ResultadoRecorridos = ConsultaRecorridos.List<Recorrido>();
            double Tiempo = 0;
            double Tiempoantes = 0;
            Boolean contando = false;
            Boolean despues = false;
            foreach (Recorrido r in ResultadoRecorridos)
            {
                if (r.Camino.Tramo.CabeceraInicial.Id == Origen.Id)
                    contando = true;
                if (r.Camino.Tramo.CabeceraInicial.Id == Destino.Id)
                {
                    despues=true;
                    contando = false;
                }
                if (contando)
                {
                    if (r.Camino.Via.Pav == 0)//Pavimentada
                        Tiempo += r.Camino.Via.Geometria.Length / 60000;
                    else
                        Tiempo += r.Camino.Via.Geometria.Length / 30000;
                }
                else
                {
                    if(!despues)
                    {
                        if (r.Camino.Via.Pav == 0)//Pavimentada
                            Tiempoantes += r.Camino.Via.Geometria.Length / 60000;
                        else
                            Tiempoantes += r.Camino.Via.Geometria.Length / 30000;
                    }
                }
                    
            }
            int HorasAntes = (int)Tiempoantes;
            int MinutosAntes = (int)((Tiempoantes-HorasAntes)*60);
            int SegundosAntes = (int)((((Tiempoantes-HorasAntes)*60)-MinutosAntes)*60);
            DateTime HoraSalida = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, servicio.Hora.Hours, servicio.Hora.Minutes, servicio.Hora.Seconds);
            TimeSpan DuracionAntes = new TimeSpan(HorasAntes, MinutosAntes, SegundosAntes);
            HoraSalida = HoraSalida.Add(DuracionAntes);
            TimeSpan Espera = HoraSalida.Subtract(Hora);
            int Horas = (int)Tiempo;
            int Minutos = (int)((Tiempo-Horas)*60);
            int Segundos = (int)((((Tiempo-Horas)*60)-Minutos)*60);
            TimeSpan Duracion = new TimeSpan(Horas, Minutos, Segundos);
            Duracion = Duracion.Add(Espera);
            return Duracion;
        }

        private TimeSpan calcularDuracionViaje(Viaje viaje)
        {
            double Tiempo = 0;
            foreach (Via v in viaje.Vias)
            {
                if (v.Pav == 0)//Pavimentada
                    Tiempo += v.Geometria.Length / 80000;
                else
                    Tiempo += v.Geometria.Length / 40000;
            }
            int Horas = (int)Tiempo;
            int Minutos = (int)((Tiempo - Horas) * 60);
            int Segundos = (int)((((Tiempo - Horas) * 60) - Minutos) * 60);
            TimeSpan Duracion = new TimeSpan((int)Tiempo, Minutos, Segundos);
            return Duracion;
        }

        private Double calcularPrecioViaje(Viaje viaje)
        {
            double distancia = 0;
            foreach (Via v in viaje.Vias)
                distancia += v.Geometria.Length;
            distancia /= 50000;
            return distancia * 8000;
        }

        private IList<Object> consultarServiciosDisponibles(Cabecera Origen, DateTime Hora, String Dia)
        {
            NHibernatePersistencia BD = (NHibernatePersistencia)NHibernatePersistencia.Instancia;
            ISQLQuery Consulta = BD.Session.CreateSQLQuery("select distinct s.id AS IDServicio, t.id_cab_fin as IDCabecera " +
                                                     "from servicio s, ruta r, recorridos re, caminos c, tramos t " +
                                                     "where s.id_ruta = r.id and " +
                                                     "re.id_ruta = r.id and " +
                                                     "re.id_camino = c.id_camino and " +
                                                     "c.id_tramo = t.id and " +
                                                     "t.id_cab_ini=? and " +
                                                     "s.dia = ?");
            Consulta.SetInt32(0, Origen.Id);
            Consulta.SetString(1, Dia);
            IList<object> Resultados = Consulta.List<object>();
            IList<Object> Servicios = new List<Object>();
            foreach (Object[] o in Resultados)
            {
                IQuery ConsultaServicio = BD.Session.CreateQuery("from Servicio where id=?");
                ConsultaServicio.SetInt32(0, (int)o[0]);
                IList<Servicio> ResultadoServicios = ConsultaServicio.List<Servicio>();
                Servicio servicio = ResultadoServicios.First<Servicio>();
                ISQLQuery ConsultaTramos = BD.Session.CreateSQLQuery("select t.id_cab_ini, t.id_cab_fin, c.orden " +
                                                     "from recorridos r, caminos c, tramos t " +
                                                     "where c.id_tramo = t.id and " +
                                                     "r.id_camino = c.id_camino and " +
                                                     "r.id_ruta = ? " +
                                                     "order by c.orden");
                ConsultaTramos.SetInt32(0, servicio.Ruta.Id);
                IList<Object> ListaTramos = ConsultaTramos.List<Object>();
                Object[] t = (Object[])ListaTramos.First();
                TimeSpan DuracionAlOrigen = new TimeSpan(0,0,0);
                if ((int)t[0] != Origen.Id)
                {
                    Cabecera ini = BD.Obtener<Cabecera>((int)t[0]);
                    //Envio la hora de salida del servicio para que no adicione tiempo de espera y solo calcule el tiempo entre el origen y el destino
                    DateTime HoraSalida = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, servicio.Hora.Hours, servicio.Hora.Minutes, servicio.Hora.Seconds);
                    DuracionAlOrigen = this.calcularDuracionServicio(servicio, ini, Origen, HoraSalida);
                }
                TimeSpan HoraEspera = new TimeSpan(Hora.Hour, Hora.Minute, Hora.Second);
                if (servicio.Hora.Add(DuracionAlOrigen) >= HoraEspera)
                {
                    int[] info = new int[2];
                    info[0] = servicio.Id;
                    info[1] = (int)o[1];
                    Servicios.Add(info);
                }
            }
            return Servicios;
        }

        private void calcularPesos(ListaNodos<Cabecera> grafo, double PesoDinero)
        {
            Hashtable TiempoAntes = new Hashtable();
            foreach (NodoGrafo<Cabecera,Medio> nodo in grafo)
            {
                if(TiempoAntes.Count==0)
                {
                    TimeSpan Duracion = new TimeSpan(0,0,0);
                    TiempoAntes[nodo.Valor]=Duracion;
                }
                foreach (NodoGrafo<Cabecera, Medio> n in nodo.Vecinos)
                {
                    DateTime Ahora = DateTime.Now;
                    if (n.Medio is Servicio)
                    {
                        Ahora = Ahora.Add((TimeSpan)TiempoAntes[nodo.Valor]);
                        TimeSpan duracion = this.calcularDuracionServicio((Servicio)n.Medio, nodo.Valor, n.Valor, Ahora);
                        Ahora = Ahora.Add(duracion);
                        if (TiempoAntes.ContainsKey(n.Valor))
                        {
                            if (((TimeSpan)TiempoAntes[n.Valor]).Ticks > duracion.Ticks)
                                TiempoAntes[n.Valor] = duracion;
                        }
                        else
                            TiempoAntes[n.Valor] = duracion;
                        nodo.Costos.Add(n.Medio.Precio*(1-PesoDinero) + duracion.Ticks*PesoDinero);
                    }
                    if (n.Medio is Vuelo)
                    {
                        TimeSpan duracion = this.calcularDuracionVuelo((Vuelo)n.Medio);
                        nodo.Costos.Add(n.Medio.Precio * (1 - PesoDinero) + duracion.Ticks * PesoDinero);
                    }
                    if (n.Medio is Viaje)
                    {
                        TimeSpan duracion = this.calcularDuracionViaje((Viaje)n.Medio);
                        n.Medio.Precio = this.calcularPrecioViaje((Viaje)n.Medio);
                        n.Costos.Add(n.Medio.Precio * (1 - PesoDinero) + duracion.Ticks * PesoDinero);
                    }
                }
            }
        }
    }
}
